<template>
  <div class="log-viewer" ref="logViewerRef" v-if="visible" :class="theme" :style="{ top: position.y + 'px', left: position.x + 'px', width: size.width + 'px', height: size.height + 'px' }">
    <div class="log-header" @mousedown="startDrag">
      <h3>系统日志</h3>
      <div class="log-actions">
        <el-switch v-model="showTimestamp" active-text="显示时间戳" inactive-text="隐藏时间戳" size="small" style="margin-right:8px" />
        <el-switch v-model="theme" :active-value="'dark'" :inactive-value="'light'" active-text="暗色" inactive-text="亮色" size="small" style="margin-right:8px" />
        <el-button size="small" type="primary" @click="clearLogs">清空日志</el-button>
        <el-button size="small" @click="$emit('close')">关闭</el-button>
      </div>
    </div>
    <div class="log-content" ref="logContentRef">
      <div v-if="logs.length === 0" class="empty-logs">暂无日志记录</div>
      <div v-else class="log-lines">
        <div v-for="(log, index) in logs" :key="index" :class="['log-line', theme]">
          <span class="log-index">{{ index + 1 }}</span>
          <span v-if="showTimestamp" class="log-timestamp">{{ formatTimestamp(log.timestamp) }}</span>
          <span class="log-text" v-html="formatLogText(log.text)"></span>
        </div>
      </div>
    </div>
    <div class="resize-handle" @mousedown="startResize"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, nextTick, onUnmounted, reactive } from 'vue';
import { useLogStore } from '../store/log';
import { storeToRefs } from 'pinia';

const props = defineProps<{
  visible: boolean
}>();

const emit = defineEmits(['close']);
const logStore = useLogStore();
const { logs } = storeToRefs(logStore);
const logContentRef = ref<HTMLElement | null>(null);
const logViewerRef = ref<HTMLElement | null>(null);
const theme = ref('light');

const position = reactive({ x: 0, y: 0 });
const size = reactive({ width: 800, height: 600 });
const dragging = ref(false);
const resizing = ref(false);
const dragStart = reactive({ x: 0, y: 0 });
const initialPosition = reactive({ x: 0, y: 0 });
const initialSize = reactive({ width: 0, height: 0 });

function startDrag(event: MouseEvent) {
  if (event.button !== 0) return;
  dragging.value = true;
  dragStart.x = event.clientX;
  dragStart.y = event.clientY;
  if (logViewerRef.value) {
    const rect = logViewerRef.value.getBoundingClientRect();
    initialPosition.x = rect.left;
    initialPosition.y = rect.top;
  }
  window.addEventListener('mousemove', onDrag);
  window.addEventListener('mouseup', stopDrag);
}

function onDrag(event: MouseEvent) {
  if (dragging.value) {
    const dx = event.clientX - dragStart.x;
    const dy = event.clientY - dragStart.y;
    position.x = initialPosition.x + dx;
    position.y = initialPosition.y + dy;
  }
}

function stopDrag() {
  dragging.value = false;
  window.removeEventListener('mousemove', onDrag);
  window.removeEventListener('mouseup', stopDrag);
}

function startResize(event: MouseEvent) {
  event.preventDefault();
  resizing.value = true;
  dragStart.x = event.clientX;
  dragStart.y = event.clientY;
  if (logViewerRef.value) {
    initialSize.width = logViewerRef.value.offsetWidth;
    initialSize.height = logViewerRef.value.offsetHeight;
  }
  window.addEventListener('mousemove', onResize);
  window.addEventListener('mouseup', stopResize);
}

function onResize(event: MouseEvent) {
  if (resizing.value) {
    const dx = event.clientX - dragStart.x;
    const dy = event.clientY - dragStart.y;
    size.width = initialSize.width + dx;
    size.height = initialSize.height + dy;
  }
}

function stopResize() {
  resizing.value = false;
  window.removeEventListener('mousemove', onResize);
  window.removeEventListener('mouseup', stopResize);
}

// 清空日志
function clearLogs() {
  logStore.clearLogs();
  if (window.systemApp) {
    window.systemApp.clearLogs();
  }
}

// 滚动到底部
function scrollToBottom() {
  nextTick(() => {
    if (logContentRef.value) {
      logContentRef.value.scrollTop = logContentRef.value.scrollHeight;
    }
  });
}

// 监听日志变化，自动滚动到底部
watch(() => logs.value.length, () => {
  scrollToBottom();
});

// 监听可见性变化，显示时滚动到底部
watch(() => props.visible, (newVal) => {
  if (newVal) {
    scrollToBottom();
    nextTick(() => {
      if (logViewerRef.value) {
        position.x = (window.innerWidth - size.width) / 2;
        position.y = (window.innerHeight - size.height) / 2;
      }
    });
  }
});

// 组件挂载时初始化日志监听
onMounted(() => {
  // 初始化日志监听
  const unsubscribe = logStore.initLogListener();
  
  // 组件卸载时取消监听
  onUnmounted(() => {
    if (unsubscribe) {
      unsubscribe();
    }
  });
});
import { ElSwitch } from 'element-plus';
import dayjs from 'dayjs';

const showTimestamp = ref(true);

function formatTimestamp(ts: string | number | undefined) {
  if (!ts) return '';
  return dayjs(ts).format('YYYY-MM-DD HH:mm:ss');
}

function formatLogText(text: string) {
  // 简单格式化：高亮 error/warn/info/debug
  let html = text
    .replace(/(error|ERROR)/g, '<span style="color:#e74c3c;font-weight:bold">$1</span>')
    .replace(/(warn|WARN)/g, '<span style="color:#f39c12;font-weight:bold">$1</span>')
    .replace(/(info|INFO)/g, '<span style="color:#3498db;font-weight:bold">$1</span>')
    .replace(/(debug|DEBUG)/g, '<span style="color:#27ae60;font-weight:bold">$1</span>');
  return html;
}
</script>

<style scoped>
.log-viewer {
  position: fixed;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  z-index: 9999;
  min-width: 300px;
  min-height: 200px;
}

.log-header {
  padding: 12px 16px;
  border-bottom: 1px solid #eee;
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: move;
}

.resize-handle {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 12px;
  height: 12px;
  cursor: se-resize;
  background: transparent;
}

.log-header h3 {
  margin: 0;
  font-size: 16px;
}

.log-actions {
  display: flex;
  gap: 8px;
}

.log-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
  background-color: #f5f7fa;
}

.empty-logs {
  padding: 20px;
  text-align: center;
  color: #909399;
}

.log-lines {
  font-family: monospace;
  font-size: 13px;
}

.log-line {
  padding: 2px 16px;
  display: flex;
  line-height: 1.5;
}

.log-line:hover {
  background-color: #ecf5ff;
}

.log-index {
  min-width: 40px;
  color: #909399;
  text-align: right;
  margin-right: 8px;
}

.log-viewer.light {
  background-color: #fff;
  color: #222;
}
.log-viewer.dark {
  background-color: #23272e;
  color: #e0e0e0;
}
.log-header.dark {
  border-bottom: 1px solid #444;
}
.log-content.dark {
  background-color: #181a20;
}
.log-line.dark {
  background-color: #23272e;
  color: #e0e0e0;
}
.log-line.light {
  background-color: #fff;
  color: #222;
}
.log-line .log-text span {
  font-weight: bold;
}
.log-line.dark:hover {
  background-color: #2c313a;
}
.log-timestamp {
  color: #888;
  font-size: 12px;
  margin-right: 8px;
}
.log-text {
  word-break: break-all;
  white-space: pre-wrap;
}
</style>